<?php

class DatabaseObject_Friends extends DatabaseObject {
    
    public static $_types = array(
        'request', 'approved', 'declined'
    );
    
    public $firstUser = null;
    public $secondUser = null;
    
    public function __construct($db) {
        parent::__construct($db, 'friends', 'id');
        $this->add('id1');
        $this->add('id2');
        $this->add('status');
    }
    
    // отправка заявки в друзья
    public static function SendRequest($db, $id1, $id2) {
        $friendship = new DatabaseObject_Friends($db);
        $friendship->id1 = $id1;
        $friendship->id2 = $id2;
        $friendship->status = 'request';
        
        $friendship->save();
        
        return true;
    }
    
    // получение статуса связи между пользователями
    public static function GetStatus($db, $id1, $id2) {
        $query = sprintf('select count(*) as count from friends where id1 = %d and id2 = %d', $id1, $id2);
        $res = $db->query($query)->fetchObject();
        
        if($res->count == 0) {
            $query = sprintf('select count(*) as count from friends where id1 = %d and id2 = %d', $id2, $id1);
            $result = $db->query($query)->fetchObject();
            
            if($result->count == 0) {
                return 'none';
            }
            else {
                $query = sprintf("select * from friends where id1 = %d and id2 = %d", $id2, $id1);
                $fs = $db->query($query)->fetchObject();

                return $fs->status;
            }
        }
        else {
            $query = sprintf("select * from friends where id1 = %d and id2 = %d", $id1, $id2);
            $fs = $db->query($query)->fetchObject();
                
            return $fs->status;
        }
    }
    
    // одобрение заявки
    public static function ApproveRequest($db, $id1, $id2) {
        $query = sprintf('update friends set status = "approved" where id1 = %d and id2 = %d', $id1, $id2);
        $db->query($query);
        
        return true;
    }
    
    // отклонение заявки
    public static function DeclineRequest($db, $id1, $id2) {
        $query = sprintf('update friends set status = "declined" where id1 = %d and id2 = %d', $id1, $id2);
        $db->query($query);
        
        return true;
    }
    
    // отклонение всех заявок
    public static function DeclineAllRequests($db, $userId) {
        $query = 'update friends set status = "request" where id2="' . $userId . '"';
        $db->query($query);
        
        return true;
    }
    
    // одобрение всех заявок
    public static function ApproveAllRequests($db, $userId) {
        $query = 'update friends set status = "request" where id2="' . $userId . '"';
        $db->query($query);
        
        return true;
    }
    
    // получение списка друзей
    public static function GetUserFriends($db, $userId, $options = array()) {
        // инициализация параметров
        $defaults = array(
            'offset' => 0,
            'limit' => 0,
            'order' => 'u.login'
        );

        foreach ($defaults as $k => $v) {
            $options[$k] = array_key_exists($k, $options) ? $options[$k] : $v;
        }

        $select = self::_GetBaseQuery($db, $options);

        // задаим поля. которые хотим получить
        $select->from(null, 'u.*');
        
        $where = sprintf('(id1 = %d or id2 = %d) and status = "approved"', $userId, $userId);
        
        $select->where($where);

        // другие параметры
        if ($options['limit'] > 0) {
            $select->limit($options['limit'], $options['offset']);
        }
            
        if ($options['order'] > 0) {
            $select->order($options['order']);
        }

        // получим данные
        $data = $db->fetchAll($select);

        // преобразуем данные в объекты класса
        $friendships = parent::BuildMultiple($db, __CLASS__, $data);
        
        $friends = array();
        
        foreach($friendships as $fs) {
            $friend = new DatabaseObject_User($db);
            if($fs->id1 == $userId) {
                $friend->load($fs->id2);
            }
            else {
                $friend->load($fs->id1);
            }
            
            $friends[] = $friend;
        }

        // вернем массив пользователей
        return $friends;
    }
    
    // получение количества друзей
    public static function GetFriendsCount($db, $userId) {
        $select = self::_GetBaseQuery($db, array());
        $select->from(null, 'count(*)');
        
        $where = sprintf('(id1 = %d or id2 = %d) and status = "approved"', $userId, $userId);
        
        $select->where($where);

        return $db->fetchOne($select);
    }
    
    // получение количества заявок
    public static function GetRequestsCount($db, $userId) {
        $select = self::_GetBaseQuery($db, array());
        $select->from(null, 'count(*)');
        
        $where = sprintf('id2 = %d and status = "request"', $userId, $userId);
        
        $select->where($where);

        return $db->fetchOne($select);
    }
    
    // получение количества собственных заявок
    public static function GetOwnRequestsCount($db, $userId) {
        $select = self::_GetBaseQuery($db, array());
        $select->from(null, 'count(*)');
        
        $where = sprintf('id1 = %d and status = "request" or status = "declined"', $userId);
        
        $select->where($where);

        return $db->fetchOne($select);
    }
    
    // получение количества отклоненных заявок
    public static function GetDeclinedRequestsCount($db, $userId) {
        $select = self::_GetBaseQuery($db, array());
        $select->from(null, 'count(*)');
        
        $where = sprintf('id1 = %d and status = "declined"', $userId);
        
        $select->where($where);

        return $db->fetchOne($select);
    }
    
    // получение заявок
    public static function GetRequests($db, $userId, $options = array()) {
        // инициализация параметров
        $defaults = array(
            'offset' => 0,
            'limit' => 0,
            'order' => 'u.login'
        );

        foreach ($defaults as $k => $v) {
            $options[$k] = array_key_exists($k, $options) ? $options[$k] : $v;
        }

        $select = self::_GetBaseQuery($db, $options);

        // задаим поля. которые хотим получить
        $select->from(null, 'u.*');
        
        $where = sprintf('id2 = %d and status = "request"', $userId);
        
        $select->where($where);

        // другие параметры
        if ($options['limit'] > 0) {
            $select->limit($options['limit'], $options['offset']);
        }
            
        if ($options['order'] > 0) {
            $select->order($options['order']);
        }

        // получим данные
        $data = $db->fetchAll($select);

        // преобразуем данные в объекты класса
        $friendships = parent::BuildMultiple($db, __CLASS__, $data);
        
        $friends = array();
        
        foreach($friendships as $fs) {
            $friend = new DatabaseObject_User($db);
            if($fs->id1 == $userId) {
                $friend->load($fs->id2);
            }
            else {
                $friend->load($fs->id1);
            }
            
            $friends[] = $friend;
        }

        // вернем массив пользователей
        return $friends;
    }
    
    // получение отклоненных заявок
    public static function GetDeclinedRequests($db, $userId, $options = array()) {
        // инициализация параметров
        $defaults = array(
            'offset' => 0,
            'limit' => 0,
            'order' => 'u.login'
        );

        foreach ($defaults as $k => $v) {
            $options[$k] = array_key_exists($k, $options) ? $options[$k] : $v;
        }

        $select = self::_GetBaseQuery($db, $options);

        // задаим поля. которые хотим получить
        $select->from(null, 'u.*');
        
        $where = sprintf('id2 = %d and status = "declined"', $userId);
        
        $select->where($where);

        // другие параметры
        if ($options['limit'] > 0) {
            $select->limit($options['limit'], $options['offset']);
        }
            
        if ($options['order'] > 0) {
            $select->order($options['order']);
        }

        // получим данные
        $data = $db->fetchAll($select);

        // преобразуем данные в объекты класса
        $friendships = parent::BuildMultiple($db, __CLASS__, $data);
        
        $friends = array();
        
        foreach($friendships as $fs) {
            $friend = new DatabaseObject_User($db);
            if($fs->id1 == $userId) {
                $friend->load($fs->id2);
            }
            else {
                $friend->load($fs->id1);
            }
            
            $friends[] = $friend;
        }

        // вернем массив пользователей
        return $friends;
    }
    
    // получение собственных заявок
    public static function GetOwnRequests($db, $userId, $options = array()) {
        // инициализация параметров
        $defaults = array(
            'offset' => 0,
            'limit' => 0,
            'order' => 'u.login'
        );

        foreach ($defaults as $k => $v) {
            $options[$k] = array_key_exists($k, $options) ? $options[$k] : $v;
        }

        $select = self::_GetBaseQuery($db, $options);

        // задаим поля. которые хотим получить
        $select->from(null, 'u.*');
        
        $where = sprintf('id1 = %d and status = "request" or status = "declined"', $userId);
        
        $select->where($where);

        // другие параметры
        if ($options['limit'] > 0) {
            $select->limit($options['limit'], $options['offset']);
        }
            
        if ($options['order'] > 0) {
            $select->order($options['order']);
        }

        // получим данные
        $data = $db->fetchAll($select);

        // преобразуем данные в объекты класса
        $friendships = parent::BuildMultiple($db, __CLASS__, $data);
        
        $friends = array();
        
        foreach($friendships as $fs) {
            $friend = new DatabaseObject_User($db);
            if($fs->id1 == $userId) {
                $friend->load($fs->id2);
            }
            else {
                $friend->load($fs->id1);
            }
            
            $friends[] = $friend;
        }

        // вернем массив пользователей
        return $friends;
    }
    
    private static function _GetBaseQuery($db, $options) {
        // инициализируем параметры
        $defaults = array('id' => array());

        foreach ($defaults as $k => $v) {
            $options[$k] = array_key_exists($k, $options) ? $options[$k] : $v;
        }

        // создадим запрос
        $select = $db->select();
        $select->from(array('u' => 'friends'), array());
        
        if(isset($options['where'])) {
            $select->where($options['where']);
        }
        if(isset($options['limit'])) {
            $select->limit($options['offset'] . ',' . $options['limit']);
        }


        // отфильтруем записи по id (если задано)
        if (count($options['id']) > 0) {
            $select->where('u.id in (?)', $options['id']);
        }

        return $select;
    }
    
    // удаление из друзей
    public static function RemoveFriend($db, $id1, $id2) {
        $query = sprintf('update friends set status = "declined" where (id1 = %d and id2 = %d) or (id1 = %d and id2 = %d)', $id1, $id2, $id2, $id1);
        $db->query($query);
    }
    
    // отмена заявки
    public static function CancelRequest($db, $id1, $id2) {
        $query = sprintf('delete from friends where id1 = %d and id2 = %d', $id1, $id2);
        $db->query($query);
    }
}